package com.seahorse.youliao.service.queue;

import com.seahorse.youliao.service.FmsPayOrderService;
import com.seahorse.youliao.service.entity.FmsPayOrderDTO;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RBlockingQueue;
import org.redisson.api.RDelayedQueue;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * @ProjectName: youliao
 * @Package: com.seahorse.youliao.service.queue
 * @ClassName: RedisDelayedQueue
 * @Description: redisson 延时队列 处理支付订单下单 半小时自动过期
 * @author:songqiang
 * @Date:2020-07-13 10:44
 **/
@Slf4j
@Component
public class RedisDelayedQueue {

    private static final String ORDER_OVERDUE_QUEUE = "order";

    @Autowired
    RedissonClient redissonClient;

    @Autowired
    private FmsPayOrderService payOrderService;



    /**
     * 添加队列
     *
     * @param orderDTO DTO传输类
     * @param delay    时间数量
     * @param timeUnit 时间单位
     */
    public void addQueueData(FmsPayOrderDTO orderDTO, long delay, TimeUnit timeUnit) {

        RBlockingQueue<FmsPayOrderDTO> blockingQueue = redissonClient.getBlockingQueue(ORDER_OVERDUE_QUEUE);
        RDelayedQueue<FmsPayOrderDTO> delayedQueue = redissonClient.getDelayedQueue(blockingQueue);
        delayedQueue.offer(orderDTO, delay, timeUnit);
        //在该对象不再需要的情况下，应该主动销毁。
        // 仅在相关的Redisson对象也需要关闭的时候可以不用主动销毁。
        delayedQueue.destroy();
    }


    /**
     * 获取队列
     *
     * @return
     */
    @PostConstruct
    public void getQueueData() {

        ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
        RBlockingQueue<FmsPayOrderDTO> blockingQueue = redissonClient.getBlockingQueue(ORDER_OVERDUE_QUEUE);

        executor.scheduleAtFixedRate(() -> {

            FmsPayOrderDTO orderDTO = blockingQueue.poll();
            if (orderDTO != null) {
                log.info("取出队列数据 订单号" + orderDTO.getOrderNo());
                //处理半小时未支付的订单自动过期
                payOrderService.handleOrderOverDue(orderDTO);
            }
        }, 30, 1, TimeUnit.SECONDS);
    }

}
